<?php 
namespace town\base;

class Log
{
    CONST DEBUG     = 'debug';     // 调试
    CONST INFO      = 'info';      // 信息
    CONST NOTICE    = 'notice';    // 请注意
    CONST WARNING   = 'warning';   // 警告
    CONST ERROR     = 'error';     // 错误
    CONST CRITICAL  = 'critical';  // 至关重要的
    CONST ALERT     = 'alert';     // 警报
    CONST EMERGENCY = 'emergency'; // 紧急

    private $file = null;
    private $list = [];
    private static $obj = null;


    private static $level = [
        E_ERROR             => 'E_ERROR',
        E_WARNING           => 'E_WARNING',
        E_PARSE             => 'E_PARSE',
        E_NOTICE            => 'E_NOTICE',
        E_CORE_ERROR        => 'E_CORE_ERROR',
        E_CORE_WARNING      => 'E_CORE_WARNING',
        E_CORE_ERROR        => 'E_CORE_ERROR',
        E_CORE_WARNING      => 'E_CORE_WARNING',
        E_USER_ERROR        => 'E_USER_ERROR',
        E_USER_WARNING      => 'E_USER_WARNING',
        E_USER_NOTICE       => 'E_USER_NOTICE',
        E_STRICT            => 'E_STRICT',
        E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
        E_DEPRECATED        => 'E_DEPRECATED',
        E_USER_DEPRECATED   => 'E_USER_DEPRECATED'
    ];

    public function __construct($file)
    {
        set_error_handler([&$this, 'handler']);
        if (empty($file)) {
            trigger_error('error_log file no exiest', E_USER_NOTICE);
        }

        $this->file = $file;
        $this->list = [];

    }

    public function handler($errno, $errstr, $errfile, $errline, array $errcontext)
    {
        $content = "FILE:$errfile LINE:$errline";
        $this->record($errno, $errstr, $content);
    }

    private function record($level, $message, $content)
    {
        list($m,$s) = explode(' ', microtime());
        $time = date('Y-m-d H:i:s.', $s).substr($m, 2);
        $this->list[] = [$time, static::$level[$level], $message, $content];
    }

    private function debug($message, $content = '')
    {
        $this->record(static::DEBUG, $message, $content);
    }

    private function info($message, $content = '')
    {
        $this->record(static::INFO, $message, $content);
    }

    private function notice($message, $content = '')
    {
        $this->record(static::NOTICE, $message, $content);
    }

    private function warning($message, $content = '')
    {
        $this->record(static::WARNING, $message, $content);
    }

    private function error($message, $content = '')
    {
        $this->record(static::ERROR, $message, $content);
    }

    private function critical($message, $content = '')
    {
        $this->record(static::CRITICAL, $message, $content);
    }

    private function alert($message, $content = '')
    {
        $this->record(static::ALERT, $message, $content);
    }

    private function emergency($message, $content = '')
    {
        $this->record(static::EMERGENCY, $message, $content);
    }

    public static function __callStatic($method, $arguments)
    {
        $obj = static::singleton();
        if (method_exists($obj, $method)) {
            return call_user_func_array([$obj, $method], $arguments);
        }
    }

    public function __destruct()
    {
        $temp = '';
        foreach ($this->list as $key => $value) {
            $temp .= implode(' ', $value).PHP_EOL;
        }
        $handle = fopen($this->file, 'a+');
        fwrite($handle, $temp);
        fclose($handle);
    }

    public static function singleton()
    {
        if (static::$obj == null) {
            $file = APP_PATH.DS.'runtime'.DS.'log'.DS.date('Y-m-d').'.log';
            static::$obj = new static($file);
        }
        return static::$obj;
    }
}
